package read_write

import (
	"errors"
	"io"
	"sync"
)

var PartWriterFull = errors.New("EOF")

// PartWriter 包装 io.Writer
// 限制 w 从设置的offset位置开始写入，最大写入 limit 数据量
// 超过limit 将抛出 EOF 错误
type PartWriter struct {
	mux     sync.Mutex
	offset  int64 //从这个位置开始写入w
	current int64
	limit   int64 //写多少长度结束， 0不限制
	w       io.Writer
}

func NewPartWriter(offset, limit int64, w io.Writer) *PartWriter {
	return &PartWriter{
		offset: offset,
		limit:  limit,
		w:      w,
	}
}

func (pw *PartWriter) Write(b []byte) (n int, err error) {
	l := int64(len(b))
	if l == 0 {
		return
	}
	pw.mux.Lock()
	defer pw.mux.Unlock()
	cc := pw.current - pw.offset
	if cc >= 0 {
		if pw.limit == 0 {
			return pw.write(b)
		} else {
			lc := pw.limit - cc
			if lc <= 0 {
				return 0, PartWriterFull
			} else {
				if l <= lc {
					return pw.write(b)
				} else {
					return pw.write(b[:lc])
				}
			}
		}
	} else {
		_lc := cc + l
		if _lc <= 0 {
			pw.current += l
			return int(l), nil
		} else {
			//_lc 数组剩余数量
			_off := l - _lc //数组开始写入数据位置
			pw.current += _off
			if pw.limit == 0 {
				return pw.write(b[_off:])
			} else {
				if pw.limit < _lc {
					return pw.write(b[_off : pw.limit+_off])
				} else {
					return pw.write(b[_off:])
				}
			}
		}
	}
}

func (pw *PartWriter) write(b []byte) (n int, err error) {
	n, err = pw.w.Write(b)
	if err != nil {
		return
	}
	pw.current += int64(n)
	if pw.limit > 0 && (pw.current-pw.offset) >= pw.limit {
		return n, PartWriterFull
	}
	return
}
